/**
 * @file       mb_callback.c
 * @author     crystal
 * @date       2021-03-05
 * @brief      modbus读写线圈和寄存器的回调函数
 * @version    1.0
 */

#include <stdint.h>

#include "mb.h"
#include "mbutils.h"
#include "mb_callback.h"

/* ----------------------- Static variables ---------------------------------*/
static uint32_t usRegInputStart = REG_INPUT_START;
uint32_t usRegInputBuf[REG_INPUT_NREGS] = {0, 0, 0x5599, 0x5588};

/* ----------------------- Static variables ---------------------------------*/
static uint32_t usRegHoldingStart = REG_HOLDING_START;
uint32_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x00, 0x00, 0x00, 0x00};


/* ----------------------- Static variables ---------------------------------*/
uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8]={0xaa,0xfe};	  //数量低于8个还需要验证一下，是否需要加1呢。


/* ----------------------- Static variables ---------------------------------*/
uint8_t ucRegDiscBuf[REG_DISC_SIZE / 8] = { 0x98, 0x6e };	   //数量8的整数倍。


eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ = ( uint8_t )( (usRegInputBuf[iRegIndex] >> 8) & 0xFF );  // 数据的高八位
            *pucRegBuffer++ = ( uint8_t )( usRegInputBuf[iRegIndex] & 0xFF );         // 数据的低八位
            
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}


eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_HOLDING_START ) && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ))
    {
        iRegIndex = ( int )( usAddress - usRegHoldingStart );
        
        switch ( eMode )
        {
            case MB_REG_READ:   // 读
                while( usNRegs > 0 )
                {
                    *pucRegBuffer++ = ( uint8_t )( (usRegHoldingBuf[iRegIndex] >> 8) & 0xFF);
                    *pucRegBuffer++ = ( uint8_t )( usRegHoldingBuf[iRegIndex] & 0xFF );
                    
                    iRegIndex++;
                    usNRegs--;
                }
                break;
            case MB_REG_WRITE:  // 写
                while( usNRegs > 0 )
                {
                    usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
                    usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
                    
                    iRegIndex++;
                    usNRegs--;
                }
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    
    return eStatus;
}



//usNCoils = 线圈数量 
//假如主站报文= 01 01 00 00 03 20 3D 22
//则usNCoils = 0x0320 = 800
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iNCoils = ( int )usNCoils;
    uint32_t  usBitOffset;

    /* Check if we have registers mapped at this block. */
    if( ( usAddress >= REG_COILS_START ) && ( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
    {
        usBitOffset = ( uint32_t )( usAddress - REG_COILS_START );
        
        switch ( eMode )
        {
            case MB_REG_READ:
                while( iNCoils > 0 )
                {
                    *pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset, ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ) );
                    iNCoils -= 8;
                    usBitOffset += 8;
                }
                break;
            case MB_REG_WRITE:
                while( iNCoils > 0 )
                {
                    xMBUtilSetBits( ucRegCoilsBuf, usBitOffset, ( uint8_t )( iNCoils > 8 ? 8 : iNCoils ), *pucRegBuffer++ );
                    iNCoils -= 8;
                    usBitOffset += 8;
                }
                break;
        }

    }
    else
    {
        eStatus = MB_ENOREG;
    }
    
    return eStatus;
}



//usNDiscrete = 离散输入数量 
//假如主站报文= 01 02 00 00 03 20 79 22
//则usNDiscrete = 0x0320 = 800
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    short           iNDiscrete = ( short )usNDiscrete;
    uint32_t  usBitOffset;

    /* Check if we have registers mapped at this block. */
    if( ( usAddress >= REG_DISC_START ) && ( usAddress + usNDiscrete <= REG_DISC_START + REG_DISC_SIZE ) )
    {
        usBitOffset = ( uint32_t )( usAddress - REG_DISC_START );
        
        while( iNDiscrete > 0 )
        {
            *pucRegBuffer++ = xMBUtilGetBits( ucRegDiscBuf, usBitOffset, ( uint8_t )( iNDiscrete > 8 ? 8 : iNDiscrete ) );
            iNDiscrete -= 8;
            usBitOffset += 8;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    
    return eStatus;
}

